#include "game_part.h"

/****************************************************************************************/

Pic::Pic(int dstLeft,int dstBottom,double dx,double dy,double dw,SDL_Surface* surface,SDL_Surface* oriSurface) {
	this->OriSurface = oriSurface;
	this->Surface = surface;
	this->moveTimes = 5;
	this->dx = dx;
	this->dy = dy;
	this->dw = dw;
	this->dst_left = dstLeft;
	this->dst_bottom = dstBottom;
	this->updateRect(dstLeft,dstBottom);
	this->dst_width = this->src.w;
}

void Pic::updateRect(int dstLeft,int dstBottom){
	int x = dstLeft;
	int y = dstBottom - this->GetSurface()->h;
	if(x < 0){
		this->src.x = -x;
		this->src.w = this->GetSurface()->w + x;
		this->dst.x = 0;
		this->dst.w = this->src.w;
	}
	else{
		this->src.x = 0;
		this->src.w = this->GetSurface()->w;
		this->dst.x = x;
		this->dst.w = this->src.w;
	}
	if(y < 0){
		this->src.y = -y;
		this->src.h = this->GetSurface()->h + y;
		this->dst.y = 0;
		this->dst.h = this->src.h;
	}
	else{
		this->src.y = 0;
		this->src.h = this->GetSurface()->h;
		this->dst.y = y;
		this->dst.h = this->src.h;
	}
}

bool Pic::Move(){
	++ this->moveTimes;
	int count = Game_Part::SumPow2(this->moveTimes);
	int w = this->dst_width + this->dw * count;
	int h = w * this->GetOriginalSurface()->h / this->GetOriginalSurface()->w;
	SDL_FreeSurface(this->Surface);
	this->Surface = Game_Image::ScaleSurface(this->GetOriginalSurface(),w);
	int x = this->dst_left + this->dx * count;
	int y = this->dst_bottom +  this->dy * count;
	this->updateRect(x,y);
	UI::UI_Rect r1(0,0,640,480);
	UI::UI_Rect r2(x,y - h,x + w,y);
	//cout << r2.ToString() << "  dx:" << dx << "   dy:" << dy << "  dw:" << dw << endl;
	return r1.Overlaps(r2);
}

bool Pic::operator > (const Pic& p) const{
	if(this->dst.y + this->Surface->h == p.dst.y + p.Surface->h){
		return this->dst.x > p.dst.x;
	}
	else
		return this->dst.y > p.dst.y;
}

bool Pic::operator == (const Pic& p) const{
	return this->dst.y + this->Surface->h == p.dst.y + p.Surface->h && this->dst.x == p.dst.x;
}

bool Pic::operator < (const Pic& p) const{
	if(this->dst.y + this->Surface->h == p.dst.y + p.Surface->h){
		return this->dst.x < p.dst.x;
	}
	else
		return this->dst.y + this->Surface->h < p.dst.y + p.Surface->h;
}

bool Pic::operator != (const Pic& p) const{ 
	return !(*this == p);
}

bool Pic::operator >= (const Pic& p) const{ 
	return !(*this < p);
}

bool Pic::operator <= (const Pic& p) const{ 
	return !(*this > p);
}

/*****************************************************************************************/

list<Game_Part*> Game_Part::part_list;
multiset<Pic> Game_Part::pictures;

void Game_Part::Destroy(vector<SDL_Surface*>& vec){
	for(vector<SDL_Surface*>::iterator it = vec.begin(); it != vec.end(); ++it)
		SDL_FreeSurface(*it);
	vec.clear();
}

void Game_Part::Destroy(list<Pic*>& vec){
	for(list<Pic*>::iterator it = vec.begin(); it != vec.end(); ++it){
		SDL_FreeSurface((*it)->GetSurface());
		delete (*it);
	}
	vec.clear();
}

void Game_Part::LoadPicture(vector<SDL_Surface*>& vec,int num,const string& folder){
	for(int i = 1; i <= num; ++i){
		string file = folder + "0" + stdex::itoa(i) + ".png";
		SDL_Surface* p = IMG_Load(file.c_str());
		if(p == NULL){
			cout << file << "   doesn't exist!" << endl;
		}
		vec.push_back(p);
	}
}

void Game_Part::add(Game_Part* part){
	part_list.push_back(part);
}

void Game_Part::Add(Pic* p){
	pictures.insert(*p);
}

void Game_Part::remove(Game_Part* part){
	for(list<Game_Part*>::iterator it = part_list.begin(); it != part_list.end(); ++it){
		if(*it == part){
			part_list.erase(it);
			return;
		}
	}
}

bool Game_Part::TickAllParts(){
	bool flag = false;
	for(list<Game_Part*>::iterator it = part_list.begin(); it != part_list.end(); ++it){
		flag |= ((*it)->TimerTick());
	}
	if(flag){
		refreshScreen();
	}
	return flag;
}

void Game_Part::refreshScreen(){
	pictures.clear();
	for(list<Game_Part*>::iterator it = part_list.begin(); it != part_list.end(); ++it){
		(*it)->UpdateToScreen();
	}
	
	SDL_Surface* screen = UI::UI_Application::Instance()->GetAppScreen();
	for(multiset<Pic>::iterator it = pictures.begin(); it != pictures.end(); ++ it){
		Pic pic = *it;
		SDL_Surface* p = pic.GetSurface();
		SDL_Rect src = (*it).SrcRect();
		SDL_Rect dst = (*it).DstRect();
		SDL_BlitSurface(p,&src,screen,&dst);
	}
}

int Game_Part::SumPow2(int num){
	int sum = 0;
	for(int i = 0; i <= num; ++i)
		sum += i * i * i * i * i;
	return sum;
}
